package io.bsly.modules.sys.ws;

import io.bsly.common.exception.RRException;
import io.bsly.common.utils.JsonUtils;
import io.bsly.common.utils.JwtUtils;
import io.bsly.modules.sys.entity.SysUserEntity;
import io.bsly.modules.sys.service.SysUserService;
import io.jsonwebtoken.Claims;
import io.netty.handler.codec.http.HttpHeaders;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.yeauty.annotation.*;
import org.yeauty.pojo.ParameterMap;
import org.yeauty.pojo.Session;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 */
//@ServerEndpoint(path = "/ws", port =8888)
@ServerEndpoint(prefix = "netty-websocket")
@Component
public class WebSocket {

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    SysUserService sysUserService;

    public static final CopyOnWriteArrayList<Session> sessionList = new CopyOnWriteArrayList<>();

    /**
     * 在线 用户名 集合
     */
    public static List<String> onlineUsers() {
        return sessionList.stream()
                .filter(p -> StringUtils.isNotEmpty(p.getAttribute("username")))
                .map(p -> p.getAttribute("username").toString())
                .collect(Collectors.toList());
    }

    @OnOpen
    public void onOpen(Session session, HttpHeaders headers, ParameterMap parameterMap) {
        sessionList.add(session);
    }

    @OnClose
    public void onClose(Session session) {
        sessionList.remove(session);
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        sessionList.remove(session);
        throwable.printStackTrace();
    }

    @OnMessage
    public void onMessage(Session session, String message) {
        WsMessage wsMessage = JsonUtils.toObject(message, WsMessage.class);
        if (wsMessage == null) {
            session.sendText("?");
            return;
        }
        switch (wsMessage.getType()) {
            case TOKEN:{
                Claims claims = jwtUtils.getClaimByToken(wsMessage.getData().toString());
                if(claims == null || jwtUtils.isTokenExpired(claims.getExpiration())){
                    throw new RRException(jwtUtils.getHeader() + "失效，请重新登录", HttpStatus.UNAUTHORIZED.value());
                }
                SysUserEntity userEntity = sysUserService.getById(Long.parseLong(claims.getSubject()));
                if (userEntity.getStatus()==0){
                    throw new RRException("用户已冻结");
                }
                session.setAttribute("username", userEntity.getUsername());
                session.setAttribute("userId", userEntity.getId());
            }
        }
    }

    /**
     * 发送消息给所有用户
     */
    public static int sendToAll(WsMessage wsMessage) {
        AtomicInteger ai = new AtomicInteger(0);
        sessionList.parallelStream()
                .filter(p -> p.isOpen())
                .forEach(p -> {
                    p.sendText(JsonUtils.toJson(wsMessage));
                    ai.incrementAndGet();
                });
        return ai.get();
    }

    /**
     * 发送消息给指定用户
     */
    public static int sendTo(String username, WsMessage wsMessage) {
        AtomicInteger ai = new AtomicInteger(0);
        sessionList.parallelStream()
                .filter(p -> p.isOpen())
                .forEach(p -> {
                    p.sendText(JsonUtils.toJson(wsMessage));
                    ai.incrementAndGet();
                });
        return ai.get();
    }
}
